/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.cvut.fel.taskpro.business.manager;

import cz.cvut.fel.taskpro.business.imanager.IGroupBusiness;
import cz.cvut.fel.taskpro.business.imanager.ITeamBusiness;
import cz.cvut.fel.taskpro.business.isupport.IBusinessRuleValidator;
import cz.cvut.fel.taskpro.business.support.BusinessRuleException;
import cz.cvut.fel.taskpro.data.entity.Assignment;
import cz.cvut.fel.taskpro.data.entity.GroupTaskPro;
import cz.cvut.fel.taskpro.data.entity.Kantor;
import cz.cvut.fel.taskpro.data.entity.Student;
import cz.cvut.fel.taskpro.data.entity.Subject;
import cz.cvut.fel.taskpro.data.entity.Team;
import cz.cvut.fel.taskpro.data.imanager.IAssignmentData;
import cz.cvut.fel.taskpro.data.imanager.IGroupData;
import cz.cvut.fel.taskpro.data.imanager.ISubjectData;
import cz.cvut.fel.taskpro.data.imanager.ITeamData;
import cz.cvut.fel.taskpro.data.imanager.IUserData;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.inject.Inject;

/**
 * This class implement #{@link IGroupBusiness} interface
 *
 * @author Tom
 * @version 1.0. beta
 */
@DeclareRoles({"admin", "kantor", "student"})
@Stateless
public class GroupBusiness implements IGroupBusiness, Serializable {

    @EJB
    private IBusinessRuleValidator validator;
    @EJB
    private ITeamBusiness teamB;
    @Inject
    private IAssignmentData assignmentData;
    @Inject
    private ISubjectData subjectData;
    @Inject
    private IGroupData groupData;
    @Inject
    private IUserData userData;
    @Inject
    private ITeamData teamData;

    public GroupBusiness() {
    }

    @RolesAllowed("admin")
    @Override
    public void addGroup(GroupTaskPro newParallel) throws BusinessRuleException {
        validator.validateAdding(newParallel);
        groupData.addGroup(newParallel);
    }

    @RolesAllowed("admin")
    @Override
    public void refreshSubject(Subject subject) {
        subjectData.refreshAllSubjects(subject);
    }

    @PermitAll
    @Override
    public List<GroupTaskPro> getGroups(List<Subject> subjects, Kantor kantor) {
        return groupData.findGroupBySubjecst(subjects, kantor);

    }

    @PermitAll
    @Override
    public List<GroupTaskPro> getGroups(Subject subject, Kantor kantor) {
        return groupData.findGroupBySubject(subject, kantor);
    }

    @Override
    public List<GroupTaskPro> getGroups(Subject subject) throws BusinessRuleException {
        validator.validate(subject);
        return groupData.getGroupsBySubject(subject);
    }

    @Override
    public void updateGroup(GroupTaskPro oldGroup, GroupTaskPro updatedGroup, List<Student> studentsToRemove) throws BusinessRuleException {
        validator.validateModification(oldGroup, updatedGroup, studentsToRemove);
        if (studentsToRemove != null) {
            Iterator stIt = studentsToRemove.iterator();
            List<Student> studentsInGroup = updatedGroup.getMStudents();
            while (stIt.hasNext()) {
                Student currStudent = (Student) stIt.next();
                if (studentsInGroup.contains(currStudent)) {
                    studentsToRemove.remove(currStudent);
                }
            }
            if (!studentsToRemove.isEmpty()) {
                Iterator stToRemoveIt = studentsToRemove.iterator();
                while (stToRemoveIt.hasNext()) {
                    Student currStudent = (Student) stToRemoveIt.next();
                    List<Assignment> assignments = assignmentData.getUnSubmitPersonalAssignments(currStudent, updatedGroup.getSubject());
                    Iterator assignmentsIt = assignments.iterator();
                    while (assignmentsIt.hasNext()) {
                        Assignment currAssignment = (Assignment) assignmentsIt.next();
                        List<Student> studentOnAssignment = currAssignment.getmStudents();
                        if (studentOnAssignment.size() == 1) {
                            List<Assignment> currStudentAssignment = currStudent.getmAssignment();
                            currStudentAssignment.remove(currAssignment);
                            currStudent.setmAssignment(currStudentAssignment);
                            userData.updateUser(currStudent);
                            assignmentData.removeAssignment(currAssignment);
                        } else {
                            List<Assignment> currStudentAssignment = currStudent.getmAssignment();
                            currStudentAssignment.remove(currAssignment);
                            currStudent.setmAssignment(currStudentAssignment);
                            studentOnAssignment.remove(currStudent);
                            currAssignment.setmStudents(studentOnAssignment);
                            userData.updateUser(currStudent);
                            assignmentData.updateAssignment(currAssignment);
                        }
                    }
                }
            }
        }
        if (!oldGroup.getKantor().equals(updatedGroup.getKantor())) {
            Kantor oldKantor = oldGroup.getKantor();
            List<GroupTaskPro> kantorsGroup = oldKantor.getmGroups();
            kantorsGroup.remove(oldGroup);
            userData.updateUser(oldKantor);
            Kantor newKantor = updatedGroup.getKantor();
            kantorsGroup = newKantor.getmGroups();
            kantorsGroup.add(oldGroup);
            userData.updateUser(newKantor);
        }
        oldGroup.setCode(updatedGroup.getCode());
        oldGroup.setDayOfTeach(updatedGroup.getDayOfTeach());
        oldGroup.setKantor(updatedGroup.getKantor());
        oldGroup.setMStudents(updatedGroup.getMStudents());
        oldGroup.setStartTime(updatedGroup.getStartTime());
        oldGroup.setStopTime(updatedGroup.getStopTime());
        oldGroup.setSubject(updatedGroup.getSubject());
        oldGroup.setmAssignments(updatedGroup.getmAssignments());
        oldGroup.setmTeams(updatedGroup.getmTeams());
        groupData.updateGroup(oldGroup);
    }

    @Override
    public void removeGroup(GroupTaskPro groupToRemove) throws BusinessRuleException {
        validator.validateRemove(groupToRemove);
        //remove teacher from group
        Kantor teacherInGroup = groupToRemove.getKantor();
        List<GroupTaskPro> kantorGroup = teacherInGroup.getmGroups();
        kantorGroup.remove(groupToRemove);
        teacherInGroup.setmGroups(kantorGroup);
        userData.updateUser(teacherInGroup);
        //remove students from group
        List<Student> students = groupToRemove.getMStudents();
        Iterator studentIt = students.iterator();
        while (studentIt.hasNext()) {
            Student studentInGroup = (Student) studentIt.next();
            List<GroupTaskPro> studentsGroup = studentInGroup.getmGroups();
            studentsGroup.remove(groupToRemove);
            studentInGroup.setmGroups(studentsGroup);
            userData.updateUser(studentInGroup);
        }
        //remove team from group
        List<Team> teamsInGroup=groupToRemove.getmTeams();
        Iterator teamIt=teamsInGroup.iterator();
        while(teamIt.hasNext()){
            Team teamToRemove=(Team) teamIt.next();
            teamData.removeTeam(teamToRemove);
        }
        groupToRemove.setmTeams(null);
        groupToRemove.setMStudents(null);
        groupData.updateGroup(groupToRemove);
        groupData.removeGroup(groupToRemove);
    }
}
